




module 	sdram_top(

	input				clk,
	input				rst,
	
	//SDRAM
	output	wire		sdram_clk,
	output	wire		sdram_cke,
	output	reg			sdram_cs_n,
	output	reg			sdram_cas_n,
	output	reg			sdram_ras_n,
	output	reg			sdram_we_n,
	output	wire[1:0]	sdram_bank,
	output	reg[12:0]	sdram_addr,
	output	wire[1:0]	sdram_dqm,
	inout		[15:0]	sdram_dq,
	
	//?
	input				write_req,
	output				write_data_valid,
	input[15:0]			write_data,
	input[12:0]			write_row,
	input[8:0]			write_col,
	output				write_ack,
	
	//?
	input				read_req,
	output[15:0]		read_data,
	input[12:0]			read_row,
	input[8:0]			read_col,
	output				read_ack,
	output				read_data_valid,
	
	
	//读写bank
	input	[1:0]			w_bank,
	input[1:0]			r_bank,
	
	
	input[7:0]			wirte_size
	

);
reg[4:0]	state,	next_state;

localparam		IDLE			=	5'b0_0001;
localparam		ARBIT			=	5'b0_0010;
localparam		AREF			=	5'b0_0100;
localparam		WRITE			=	5'b0_1000;
localparam		READ			= 	5'b1_0000;





//init-----------
wire			flag_init_end;
wire	[3:0]	init_cmd;
wire	[12:0]	init_addr;

sdram_init sdram_init_inst(

	.sclk(clk),	//100M
	.s_rst_n(rst),
	
	.cmd_reg(init_cmd),
	.sdram_addr(init_addr),
	.flag_init_end(flag_init_end)
);

//--------------------------------------


//aref---------------------------------------------
wire			aref_req;
wire[3:0]		aref_cmd;
wire[12:0]		aref_addr;

wire			flag_aref_end;
reg				aref_en;

sdram_aref sdram_aref_nst(
	
	.clk(clk),
	.rst(rst),
	
	
	.aref_en(aref_en),
	.aref_req(aref_req),
	.aref_end(flag_aref_end),
	
	
	.aref_cmd(aref_cmd),
	.aref_addr(aref_addr),

	.flag_init_end(flag_init_end)
);



always@(posedge clk or negedge rst)
begin
	if(rst == 1'b0)
		aref_en <= 1'b0;
	else if(state == ARBIT)
		if(aref_req == 1'b1)
			aref_en <= 1'b1;
		else
			aref_en <= 1'b0;
	else if(flag_aref_end == 1'b1)
		aref_en <= 1'b0;
end

//-----------------------------------------------



//write----------------------------------------
reg				write_en;
wire			write_valid;
wire 			flag_write_end;
wire[3:0]		write_cmd;
wire[12:0]		write_addr;
wire			write_valid_test;

sdram_write sdram_write_inst(
	
		.clk(clk),
		.rst(rst),
		
		.write_en(write_en),
		.write_valid(write_valid),
		.flag_write_end(flag_write_end),
		.write_valid_test(write_valid_test),
		
		.write_addr(write_addr),
		.write_cmd(write_cmd),
		
		.write_row(write_row),
		.write_col(write_col),
		.wirte_size(wirte_size)
);

always@(posedge clk or negedge rst)
begin
	if(rst == 1'b0)
		write_en <= 1'b0;
	else if(flag_write_end == 1'b1)
		write_en <= 1'b0;
	else if(state == WRITE)
		write_en = 1'b1;
end

assign write_ack	=	(flag_write_end == 1'b1) ? 1'b1 : 1'b0;
assign sdram_dq = (write_valid == 1'b1) ? write_data : 'dz;
assign write_data_valid = write_valid_test;
//---------------------------------------------

//read-------------------------------------------------
reg				read_en;
wire			read_valid;
wire 			flag_read_end;
wire[3:0]		read_cmd;
wire[12:0]		read_addr;

sdram_read sdram_read_inst(
	
		.clk(clk),
		.rst(rst),
		
		.read_en(read_en),
		.read_valid(read_valid),
		.flag_read_end(flag_read_end),
		
		
		.read_addr(read_addr),
		.read_cmd(read_cmd),
		
		.read_row(read_row),
		.read_col(read_col)
);
always@(posedge clk or negedge rst)
begin
	if(rst == 1'b0)
		read_en <= 1'b0;
	else if(flag_read_end == 1'b1)
		read_en <= 1'b0;
	else if(state == READ)
		read_en = 1'b1;
end

assign	read_ack = (flag_read_end == 1'b1) ? 1'b1 : 1'b0;
assign  read_data = (read_valid == 1'b1) ? sdram_dq : 'dz;
assign  read_data_valid = read_valid;
//-------------------------------------------------


//-----------state-----------------------------------------


always@(posedge clk or negedge rst)
begin
	if(rst == 1'b0)
		state <= IDLE;
	else
		state <= next_state;
end


always@(*)
begin
	case(state)
	IDLE:
		if(flag_init_end == 1'b1)
			next_state <= ARBIT;
		else
			next_state <= IDLE;
	ARBIT:
		if(aref_req == 1'b1)
			next_state <= AREF;
		else if(write_req == 1'b1)
			next_state <=	WRITE;
		else if(read_req == 1'b1)
			next_state <= READ;
		else
			next_state <= ARBIT;
	AREF:
		if(flag_aref_end == 1'b1)
			next_state <= ARBIT;
		else
			next_state <= AREF;
	WRITE:
		if(flag_write_end == 1'b1)
			next_state <= ARBIT;
		else
			next_state <= WRITE;
	READ:
		if(flag_read_end ==1'b1)
			next_state <= ARBIT;
		else
			next_state <= READ;
	default:
			next_state <= IDLE;
	endcase	
end


//????
always@(posedge clk or negedge rst)
begin
	if(rst == 1'b0)
		{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= 4'd0;
	else if(state == IDLE)
		{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= init_cmd;
	else if(state == AREF)
		{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= aref_cmd;
	else if(state == WRITE)
		{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= write_cmd;
	else if(state == READ)
		{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= read_cmd;
	else
		{sdram_cs_n,sdram_ras_n,sdram_cas_n,sdram_we_n} <= 4'd0111;		//nop??????
end

//????
always@(posedge clk or negedge rst)
begin
	if(rst == 1'b0)
		sdram_addr <=	'd0;
	else if(state == IDLE)
		sdram_addr <=	init_addr;
	else if(state == AREF)
		sdram_addr <=	aref_addr;
	else if(state == WRITE)
		sdram_addr <=	write_addr;
	else if(state == READ)
		sdram_addr <= 	read_addr;
	else
		sdram_addr <= 'd0;
end

assign	sdram_cke		=		1'b1;
assign	sdram_dqm		=		2'b00;
assign	sdram_clk		=		~clk;
assign  sdram_bank		= 		(state == WRITE) ? w_bank : r_bank;
//----------------------------------------------------------

endmodule	